home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AMIGA-CD 2
/
Amiga-CD - Volume 2.iso
/
gepackte_disketten
/
1994
/
08_94_5.dms
/
08_94_5.adf
/
term-4.0-Source.lha
/
termConsole.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-09
|
51KB
|
3,015 lines
/*
** termConsole.c
**
** High-level terminal console routines
**
** Copyright © 1990-1994 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
#include "termGlobal.h"
#include "termEmulationProcess.h"
/* Character set modes. */
enum { MODE_STANDARD,MODE_GFX };
/* Hints for the data flow scanner. */
STATIC WORD ScanStart,
ScanEnd;
STATIC WORD __far AttentionCount[SCAN_COUNT],
AttentionLength[SCAN_COUNT],
FlowCount;
/* Temporary console working buffer. */
STATIC UBYTE __far ConTempBuffer[512];
/* Text output data. */
STATIC UBYTE CurrentFontScale,FontScalingRequired;
STATIC WORD LastPrintableColumn;
/* ConTranslateSetup():
*
* Set up for buffer translation.
*/
STATIC VOID __inline
ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
{
Handle -> LocalBuffer = NULL;
Handle -> LocalLen = 0;
Handle -> SourceBuffer = SourceBuffer;
Handle -> SourceLen = SourceLen;
Handle -> DestinationBuffer = DestinationBuffer;
Handle -> DestinationLen = DestinationLen;
Handle -> Table = Table;
}
/* ConTranslateBuffer(struct TranslationHandle *Handle):
*
* Translate buffer contents according to
* translation table contents.
*/
STATIC LONG __inline
ConTranslateBuffer(struct TranslationHandle *Handle)
{
register STRPTR Data = Handle -> DestinationBuffer;
register LONG BytesWritten = 0;
register struct TranslationEntry *Entry;
/* Are we to return any translated data? */
while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
{
/* Decrement number of bytes in buffer. */
Handle -> LocalLen--;
/* Return next character. */
*Data++ = *Handle -> LocalBuffer++;
/* Add another byte. */
BytesWritten++;
}
/* Loop until done. */
while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
{
/* Another byte eaten. */
Handle -> SourceLen--;
/* Get table entry. */
if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
{
/* Copy to local data area. */
Handle -> LocalBuffer = Entry -> String;
Handle -> LocalLen = Entry -> Len;
/* Translate the data. */
while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
{
/* Decrement number of bytes in buffer. */
Handle -> LocalLen--;
/* Return next character. */
*Data++ = *Handle -> LocalBuffer++;
/* Add another byte. */
BytesWritten++;
}
}
}
return(BytesWritten);
}
/* TrapFilter(register STRPTR Data,register LONG Size):
*
* Handle the trap list, similar to FlowFilter().
*/
STATIC VOID __regargs
TrapFilter(register STRPTR Data,register LONG Size)
{
STATIC LONG WaitCount = 0;
struct List *List = (struct List *)&GenericListTable[GLIST_TRAP] -> ListHeader;
struct TrapNode *Node;
register UBYTE c,Mask;
ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
if(Config -> SerialConfig -> StripBit8)
Mask = 0x7F;
else
Mask = 0xFF;
do
{
register BOOLEAN MatchMade;
c = (*Data++) & Mask;
do
{
MatchMade = FALSE;
for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
{
if(Node -> Count == WaitCount)
{
if(c == (Node -> Sequence[WaitCount] & Mask))
{
MatchMade = TRUE;
if(++Node -> Count == Node -> SequenceLen)
{
struct DataMsg *Msg;
Node -> Count = 0;
if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + strlen(Node -> Command) + 1))
{
Msg -> Type = DATAMSGTYPE_SERIALCOMMAND;
Msg -> Data = (STRPTR)(Msg + 1);
strcpy(Msg -> Data,Node -> Command);
PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
}
}
}
}
}
if(MatchMade)
WaitCount++;
else
{
if(WaitCount)
{
WaitCount = 0;
for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
Node -> Count = 0;
}
else
break;
}
}
while(!WaitCount);
}
while(--Size);
ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
}
/* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
*
* Data flow filter.
*/
STATIC VOID __regargs
FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
{
register UBYTE c;
/* Run until done. */
do
{
if(c = (*Data++ & Mask))
{
/* We already got a `CONNECT',
* Continue scanning the serial output
* data for the actual baud rate.
*/
if(BaudPending)
{
if(c < ' ')
{
while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
BaudCount--;
BaudBuffer[BaudCount] = 0;
FlowInfo . Connect = TRUE;
FlowInfo . Changed = TRUE;
BaudPending = FALSE;
DTERate = GetBaudRate(BaudBuffer);
if(Quiet && Size > 1)
{
DataHold = Data;
DataSize = Size - 1;
}
}
else
{
if(BaudCount || c != ' ')
{
BaudBuffer[BaudCount++] = c;
if(BaudCount == 79)
{
while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
BaudCount--;
BaudBuffer[BaudCount] = 0;
FlowInfo . Connect = TRUE;
FlowInfo . Changed = TRUE;
BaudPending = FALSE;
DTERate = GetBaudRate(BaudBuffer);
if(Quiet && Size > 1)
{
DataHold = Data;
DataSize = Size - 1;
}
}
}
}
}
else
{
register BYTE MatchMade;
register WORD i;
do
{
MatchMade = FALSE;
/* Scan all ID strings for matches. */
for(i = ScanStart ; i <= ScanEnd ; i++)
{
/* This sequence is a likely
* match.
*/
if(AttentionCount[i] == FlowCount)
{
/* Does the character
* fit into the sequence?
*/
if(c == AttentionBuffers[i][FlowCount] & Mask)
{
MatchMade = TRUE;
/* Did we hit the
* last character
* in the sequence?
*/
if(++AttentionCount[i] == AttentionLength[i])
{
/* We've got a valid
* sequence, now look
* which flags to change.
*/
switch(i)
{
/* We got a `no carrier' message. */
case SCAN_NOCARRIER:
if(Config -> SerialConfig -> CheckCarrier)
{
WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(WriteRequest);
/* Is the carrier still present? */
if(!(WriteRequest -> io_Status & CIAF_COMCD))
break;
}
if(!FlowInfo . NoCarrier)
{
FlowInfo . NoCarrier = TRUE;
FlowInfo . Changed = TRUE;
}
WasOnline = Online;
Online = FALSE;
/* Clear the password. */
Password[0] = 0;
UserName[0] = 0;
CurrentBBSName[0] = 0;
CurrentBBSComment[0] = 0;
CurrentBBSNumber[0] = 0;
if(WasOnline)
{
StopCall(FALSE);
Say(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
SetDialMenu(TRUE);
}
break;
/* Got another call. */
case SCAN_RING:
if(!FlowInfo . Ring)
{
FlowInfo . Ring = TRUE;
FlowInfo . Changed = TRUE;
}
break;
/* Got a voice call. */
case SCAN_VOICE:
if(!FlowInfo . Voice)
{
FlowInfo . Voice = TRUE;
FlowInfo . Changed = TRUE;
}
break;
/* Got a connect message. */
case SCAN_CONNECT:
/* Are we to check the carrier signal? */
if(Config -> SerialConfig -> CheckCarrier)
{
WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
DoIO(WriteRequest);
/* Is the carrier signal present, i.e.
* was the `CONNECT' message valid?
*/
if(WriteRequest -> io_Status & CIAF_COMCD)
break;
}
WasOnline = Online;
if(!Online)
{
BaudBuffer[0] = 0;
BaudPending = TRUE;
BaudCount = 0;
}
break;
/* Got the ZModem inquiry sequence. */
case SCAN_ZMODEM:
if(!FlowInfo . ZModemUpload)
{
FlowInfo . ZModemUpload = TRUE;
FlowInfo . Changed = TRUE;
}
break;
/* Line is busy. */
case SCAN_BUSY:
if(!FlowInfo . Busy)
{
FlowInfo . Busy = TRUE;
FlowInfo . Changed = TRUE;
}
break;
case SCAN_NODIALTONE:
if(!FlowInfo . NoDialTone)
{
FlowInfo . NoDialTone = TRUE;
FlowInfo . Changed = TRUE;
}
break;
}
}
}
}
}
if(MatchMade)
FlowCount++;
else
{
if(FlowCount)
{
FlowCount = 0;
memset(AttentionCount,0,sizeof(AttentionCount));
}
else
break;
}
}
while(!FlowCount);
}
}
}
while(--Size);
}
/* StripSequence():
*
* Strips a string from ESC and CSI introduced control
* sequences.
*/
STATIC LONG __regargs
StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
{
STATIC BYTE HasESC = FALSE,
HasCSI = FALSE;
LONG Size = 0;
while(Length--)
{
if(HasESC)
{
if(*Src == '[')
{
HasESC = FALSE;
HasCSI = TRUE;
}
else
{
if(*Src >= '0')
HasESC = FALSE;
}
Src++;
continue;
}
if(HasCSI)
{
if(*Src >= '@')
HasCSI = FALSE;
Src++;
continue;
}
switch(*Src)
{
case CAN:
case SUB:
HasESC = HasCSI = FALSE;
break;
case '\r':
break;
case ESC:
HasESC = TRUE;
break;
case CSI:
HasCSI = TRUE;
break;
default:
if(IsPrintable[*Src])
{
*Dst++ = *Src;
Size++;
}
break;
}
Src++;
}
return(Size);
}
/* ConOutputPrinter(STRPTR Buffer,LONG Size):
*
* Raw text output routine, printer capture flavour.
*/
STATIC VOID
ConOutputPrinter(STRPTR Buffer,LONG Size)
{
if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
{
BlockWindows();
if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
ClosePrinterCapture(TRUE);
ReleaseWindows();
}
}
/* ConOutputCaptureGFX(STRPTR Buffer,LONG Size):
*
* Raw text output routine, GFX text & capture flavour.
*/
STATIC VOID
ConOutputCaptureGFX(STRPTR Buffer,LONG Size)
{
register WORD Offset;
/* Do we still have a character in the
* magnificient buffer?
*/
while(Size)
{
/* Cursor is positioned at
* the right hand side of the
* display. If auto-wrap is
* enabled, perform some
* kind of CR/LF, else leave
* the cursor where it is and
* quit the show.
*/
if(CursorX > LastPrintableColumn)
{
/* Wrap cursor. */
if(Config -> EmulationConfig -> LineWrap)
{
/* Move to beginning of next line. */
CursorX = 0;
DownLine();
Capture("\n",1);
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
/* Reposition cursor, don't redraw it. */
ClipBlitCursor(FALSE,TRUE);
}
else
{
/* Stop the cursor. */
CursorX = LastPrintableColumn;
Capture(Buffer,Size);
/* Make it reappear. */
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
GfxText(RPort,Buffer,Offset);
Capture(Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConOutputCaptureNormal(STRPTR Buffer,LONG Size):
*
* Raw text output routine, normal text & capture flavour.
*/
STATIC VOID
ConOutputCaptureNormal(STRPTR Buffer,LONG Size)
{
register WORD Offset;
while(Size)
{
if(CursorX > LastPrintableColumn)
{
if(Config -> EmulationConfig -> LineWrap)
{
CursorX = 0;
DownLine();
Capture("\n",1);
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
ClipBlitCursor(FALSE,TRUE);
}
else
{
CursorX = LastPrintableColumn;
Capture(Buffer,Size);
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
Text(RPort,Buffer,Offset);
Capture(Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConOutputGFX(STRPTR Buffer,LONG Size):
*
* Raw text output routine, GFX text flavour.
*/
STATIC VOID
ConOutputGFX(STRPTR Buffer,LONG Size)
{
register WORD Offset;
/* Do we still have a character in the
* magnificient buffer?
*/
while(Size)
{
/* Cursor is positioned at
* the right hand side of the
* display. If auto-wrap is
* enabled, perform some
* kind of CR/LF, else leave
* the cursor where it is and
* quit the show.
*/
if(CursorX > LastPrintableColumn)
{
/* Wrap cursor. */
if(Config -> EmulationConfig -> LineWrap)
{
/* Move to beginning of next line. */
CursorX = 0;
DownLine();
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
/* Reposition cursor, don't redraw it. */
ClipBlitCursor(FALSE,TRUE);
}
else
{
/* Stop the cursor. */
CursorX = LastPrintableColumn;
/* Make it reappear. */
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
GfxText(RPort,Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConOutputNormal(STRPTR Buffer,LONG Size):
*
* Raw text output routine, normal text flavour.
*/
STATIC VOID
ConOutputNormal(STRPTR Buffer,LONG Size)
{
register WORD Offset;
while(Size)
{
if(CursorX > LastPrintableColumn)
{
if(Config -> EmulationConfig -> LineWrap)
{
CursorX = 0;
DownLine();
CurrentFontScale = SCALE_ATTR_NORMAL;
FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
LastPrintableColumn = LastColumn;
ClipBlitCursor(FALSE,TRUE);
}
else
{
CursorX = LastPrintableColumn;
ClipBlitCursor(FALSE,TRUE);
return;
}
}
if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
Offset = Size;
if(Config -> EmulationConfig -> InsertMode)
{
RasterShiftChar(Offset);
ScrollLineShiftChar(Offset);
ShiftChar(Offset);
}
RasterPutString(Buffer,Offset);
ScrollLinePutString(Offset);
if(FontScalingRequired)
PrintScaled(Buffer,Offset,CurrentFontScale);
else
Text(RPort,Buffer,Offset);
Buffer += Offset;
Size -= Offset;
CursorX += Offset;
}
ClipBlitCursor(FALSE,TRUE);
}
/* ConProcessUpdate():
*
* Choose the right console data processing routine.
*/
VOID
ConProcessUpdate(VOID)
{
Forbid();
if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
{
if(ReceiveTable)
ConProcessData = ConProcessDataTransExternal;
else
ConProcessData = ConProcessDataExternal;
}
else
{
if(Config -> SerialConfig -> StripBit8)
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
ConProcessData = ConProcessDataHex7;
else
ConProcessData = ConProcessData7;
}
else
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
ConProcessData = ConProcessDataHex8;
else
ConProcessData = ConProcessData8;
}
}
Permit();
}
/* ConOutputUpdate():
*
* Choose the right raw text output routine for the job.
*/
VOID
ConOutputUpdate()
{
Forbid();
if(ControllerActive)
ConOutput = ConOutputPrinter;
else
{
if((Config -> CaptureConfig -> CaptureFilterMode && FileCapture) || PrinterCapture)
{
if(CurrentFont == GFX)
ConOutput = ConOutputCaptureGFX;
else
ConOutput = ConOutputCaptureNormal;
}
else
{
if(BufferFrozen)
{
if(CurrentFont == GFX)
ConOutput = ConOutputGFX;
else
ConOutput = ConOutputNormal;
}
else
{
if(CurrentFont == GFX)
ConOutput = ConOutputCaptureGFX;
else
ConOutput = ConOutputCaptureNormal;
}
}
}
if(ReceiveTable)
ConDump = ConTransWrite;
else
ConDump = ConOutput;
Permit();
}
/* ConFontScaleUpdate():
*
* Choose the right font scale for the job.
*/
VOID
ConFontScaleUpdate()
{
CurrentFontScale = RasterAttr[CursorY];
if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
{
FontScalingRequired = (CurrentFontScale != SCALE_ATTR_2X);
LastPrintableColumn = LastColumn;
}
else
{
if(FontScalingRequired = (CurrentFontScale != SCALE_ATTR_NORMAL))
LastPrintableColumn = ((LastColumn + 1) / 2) - 1;
else
LastPrintableColumn = LastColumn;
}
}
/* ConTransWrite(STRPTR Buffer,LONG Size):
*
* Frontend for ConWrite(), including character translation.
*/
VOID
ConTransWrite(STRPTR Buffer,LONG Size)
{
struct TranslationHandle Handle;
UBYTE LocalBuffer[256];
/* Set up for translation. */
ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
/* Process and output the data. */
while(Size = ConTranslateBuffer(&Handle))
(* ConOutput)(LocalBuffer,Size);
}
/* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
*
* Process data, external emulation including translation flavour.
*/
VOID
ConProcessDataTransExternal(register STRPTR String,register LONG Size)
{
struct TranslationHandle Handle;
/* Set up for translation. */
ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
if(StripBuffer)
{
register LONG Len;
/* Process and output the data. */
while(Size = ConTranslateBuffer(&Handle))
{
XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
XEM_HostData . Source = ConTempBuffer;
XEM_HostData . Destination = StripBuffer;
if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
Capture(StripBuffer,Len);
}
}
else
{
/* Process and output the data. */
while(Size = ConTranslateBuffer(&Handle))
XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
}
}
/* ConProcessDataExternal(register STRPTR String,register LONG Size):
*
* Process data, external emulation flavour.
*/
VOID
ConProcessDataExternal(register STRPTR String,register LONG Size)
{
XEmulatorWrite(XEM_IO,String,Size);
/* Build another string to contain
* the pure ASCII contents, i.e.
* not including any ESC control
* sequences.
*/
if(StripBuffer)
{
register LONG Len;
XEM_HostData . Source = String;
XEM_HostData . Destination = StripBuffer;
if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
Capture(StripBuffer,Len);
}
}
/* ConProcessData7(register STRPTR String,register LONG Size):
*
* Process data, 7 bit flavour.
*/
VOID
ConProcessData7(register STRPTR String,register LONG Size)
{
register LONG Len = 0;
register UBYTE c;
// Check for prescroll
if(CursorY == LastLine && LastLine > 0)
{
LONG Scroll = 0;
if(Config -> EmulationConfig -> MaxScroll)
{
register WORD Count = MIN(Config -> EmulationConfig -> MaxScroll,Size);
if(Count > 1)
{
register UBYTE *Buffer = String;
register LONG Total = 0;
while(Count--)
{
if((*Buffer++ & 0x7F) == '\n')
Total++;
}
if(Config -> EmulationConfig -> MaxJump > Total)
Scroll = Config -> EmulationConfig -> MaxJump;
else
Scroll = Total;
}
}
else
{
if(Config -> EmulationConfig -> MaxJump)
{
WORD Count = MIN(Config -> EmulationConfig -> MaxJump,Size);
if(Count > 1)
{
register UBYTE *Buffer = String;
register LONG Look = LastColumn + 1;
while(Look--)
{
if((*Buffer++ & 0x7F) == '\n')
{
if(Count > Scroll)
Scroll = Count;
break;
}
}
}
}
}
if(Scroll > 1)
{
if(Scroll > LastLine - 1)
Scroll = LastLine - 1;
ScrollRegion(Scroll);
CursorY -= Scroll;
ClipBlitCursor(FALSE,TRUE);
}
}
/* If still parsing a sequence,
* continue with it.
*/
if(InSequence)
{
while(Size--)
{
c = *String++ & 0x7F;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
/* Check which font we are in, if other than Topaz
* the only invalid char is a Null (0) which will
* display as a space if let to continue.
*/
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
while(Size-- > 0)
{
if(IsPrintable[c = *String++ & 0x7F])
{
/* This character is associated with a
* special function (bell, xon, xoff, etc.).
*/
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
/* Does this character start
* a control sequence?
*/
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++ & 0x7F;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
/* Put the character into the buffer
* and flush it if necessary.
*/
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
else
{
while(Size-- > 0)
{
if(c = (*String++ & 0x7F))
{
/* This character is associated with a
* special function (bell, xon, xoff, etc.).
*/
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++ & 0x7F;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
/* Put the character into the buffer
* and flush it if necessary.
*/
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
if(Len)
(*ConDump)(ConTempBuffer,Len);
}
/* ConProcessData8(register STRPTR String,register LONG Size):
*
* Process data, 8 bit flavour.
*/
VOID
ConProcessData8(register STRPTR String,register LONG Size)
{
register LONG Len = 0;
register UBYTE c;
// Check for prescroll
if(CursorY == LastLine && LastLine > 0)
{
LONG Scroll = 0;
if(Config -> EmulationConfig -> MaxScroll)
{
register WORD Count = MIN(Config -> EmulationConfig -> MaxScroll,Size);
if(Count > 1)
{
register UBYTE *Buffer = String;
register LONG Total = 0;
while(Count--)
{
if(*Buffer++ == '\n')
Total++;
}
if(Config -> EmulationConfig -> MaxJump > Total)
Scroll = Config -> EmulationConfig -> MaxJump;
else
Scroll = Total;
}
}
else
{
if(Config -> EmulationConfig -> MaxJump)
{
WORD Count = MIN(Config -> EmulationConfig -> MaxJump,Size);
if(Count > 1)
{
register UBYTE *Buffer = String;
register LONG Look = LastColumn + 1;
while(Look--)
{
if(*Buffer++ == '\n')
{
if(Count > Scroll)
Scroll = Count;
break;
}
}
}
}
}
if(Scroll > 1)
{
if(Scroll > LastLine - 1)
Scroll = LastLine - 1;
ScrollRegion(Scroll);
CursorY -= Scroll;
ClipBlitCursor(FALSE,TRUE);
}
}
if(InSequence)
{
while(Size--)
{
c = *String++;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
while(Size-- > 0)
{
if(IsPrintable[c = *String++])
{
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
else
{
while(Size-- > 0)
{
if(c = *String++)
{
if(SpecialTable[c])
{
if(Len)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
if(InSequence = (*SpecialTable[c])(c))
{
while(Size-- > 0)
{
c = *String++;
if(!(*AbortTable[c])(c))
{
InSequence = FALSE;
break;
}
}
}
}
else
{
ConTempBuffer[Len] = c;
if(Len++ == 512)
{
(*ConDump)(ConTempBuffer,Len);
Len = 0;
}
}
}
}
}
if(Len)
(*ConDump)(ConTempBuffer,Len);
}
/* ConProcessDataHex7(register STRPTR String,register LONG Size):
*
* Process data, hex mode flavour, seven bits.
*/
VOID
ConProcessDataHex7(register STRPTR String,register LONG Size)
{
UBYTE DummyBuffer[40],c;
LONG Fit,Spaces,Current;
/* How many characters will fit into the line? */
Fit = (LastColumn + 1) / 4;
/* Which position are we currently in? */
Current = CursorX / 3;
/* Weird cursor position? */
if(Current >= Fit || (CursorX % 3))
{
ConProcessData7("\r\n",2);
Current = 0;
}
/* Check the font type. */
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
while(Size-- > 0)
{
c = (*String++) & 0x7F;
Spaces = (Fit - Current) * 3 + Current - 3;
if(c > ' ' && c < 127)
SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
else
SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
ConProcessData7(DummyBuffer,strlen(DummyBuffer));
if(Current++ == Fit - 1)
{
Current = 0;
ConProcessData7("\r\n",2);
}
}
}
else
{
while(Size-- > 0)
{
c = (*String++) & 0x7F;
Spaces = (Fit - Current) * 3 + Current - 3;
if(c && c != ' ')
SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
else
SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
ConProcessData7(DummyBuffer,strlen(DummyBuffer));
if(Current++ == Fit - 1)
{
Current = 0;
ConProcessData7("\r\n",2);
}
}
}
}
/* ConProcessDataHex8(register STRPTR String,register LONG Size):
*
* Process data, hex mode flavour, eight bits.
*/
VOID
ConProcessDataHex8(register STRPTR String,register LONG Size)
{
UBYTE DummyBuffer[40],c;
LONG Fit,Spaces,Current;
/* How many characters will fit into the line? */
Fit = (LastColumn + 1) / 4;
/* Which position are we currently in? */
Current = CursorX / 3;
/* Weird cursor position? */
if(Current >= Fit || (CursorX % 3))
{
ConProcessData8("\r\n",2);
Current = 0;
}
/* Check the font type. */
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
while(Size-- > 0)
{
c = *String++;
Spaces = (Fit - Current) * 3 + Current - 3;
if((c > ' ' && c < 127) || c > 160)
SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
else
SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
ConProcessData8(DummyBuffer,strlen(DummyBuffer));
if(Current++ == Fit - 1)
{
Current = 0;
ConProcessData8("\r\n",2);
}
}
}
else
{
while(Size-- > 0)
{
c = *String++;
Spaces = (Fit - Current) * 3 + Current - 3;
if(c && c != ' ')
SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
else
SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
ConProcessData8(DummyBuffer,strlen(DummyBuffer));
if(Current++ == Fit - 1)
{
Current = 0;
ConProcessData8("\r\n",2);
}
}
}
}
/* ConTransferHost(STRPTR Buffer,LONG Len):
*
* Process data read from the serial line,
* special XPR flavour.
*/
VOID
ConTransferHost(STRPTR Buffer,LONG Len)
{
Len = XProtocolHostMon(XprIO,Buffer,Len,Config -> SerialConfig -> SerialBufferSize);
if(TransferWindow)
TransferCleanup();
if(Len)
ConProcess(Buffer,Len);
}
/* ConsoleCommand(STRPTR String):
*
* Just like SerialCommand(), but addresses the local
* terminal side.
*/
VOID
ConsoleCommand(STRPTR String)
{
STATIC UBYTE __far LocalBuffer[256];
LONG Count = 0,i,Len = strlen(String);
BYTE GotControl = FALSE,
GotEscape = FALSE;
/* Scan the string. */
for(i = 0 ; i < Len ; i++)
{
/* We are looking for plain characters
* and the control ('\') and escape
* ('^') characters.
*/
if(!GotControl && !GotEscape)
{
/* Got a control character,
* the next byte will probably be
* a command sequence.
*/
if(String[i] == '\\')
{
GotControl = TRUE;
continue;
}
/* Got an escape character,
* the next byte will be some
* kind of control character
* (such as XON, XOF, bell, etc.).
*/
if(String[i] == '^')
{
GotEscape = TRUE;
continue;
}
/* This tells us to wait another
* second before continuing with
* the scanning.
*/
if(String[i] == '~')
continue;
/* Stuff the character into the
* buffer.
*/
LocalBuffer[Count++] = String[i];
}
else
{
/* Convert the character to a control
* style character (^C, etc.).
*/
if(GotEscape)
{
if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
LocalBuffer[Count++] = ToUpper(String[i]) - '@';
else
LocalBuffer[Count++] = String[i];
GotEscape = FALSE;
}
/* The next character represents a command. */
if(GotControl)
{
switch(ToUpper(String[i]))
{
/* Translate code. */
case '*':
i++;
while(i < Len && String[i] == ' ')
i++;
if(i < Len)
{
UBYTE DummyBuffer[5],j = 0,Char;
if(String[i] >= '0' && String[i] <= '9')
{
while(j < 3 && i < Len)
{
Char = String[i++];
if(Char >= '0' && Char <= '9')
DummyBuffer[j++] = Char;
else
{
i--;
break;
}
}
}
else
{
while(j < 4 && i < Len)
{
Char = ToLower(String[i++]);
if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
DummyBuffer[j++] = Char;
else
{
i--;
break;
}
}
}
DummyBuffer[j] = 0;
LocalBuffer[Count++] = NameToCode(DummyBuffer);
}
i--;
break;
/* Execute an AmigaDOS command. */
case 'D':
return;
/* Execute an ARexx command. */
case 'A':
return;
/* Add the control character ('\'). */
case '\\':
LocalBuffer[Count++] = '\\';
break;
/* This is a backspace. */
case 'B':
LocalBuffer[Count++] = '\b';
break;
/* This is a form feed. */
case 'F':
LocalBuffer[Count++] = '\f';
break;
/* This is a line feed. */
case 'N':
LocalBuffer[Count++] = '\n';
break;
/* Send the current password. */
case 'P':
break;
/* This is a carriage return. */
case 'R':
LocalBuffer[Count++] = '\r';
break;
/* This is a tab. */
case 'T':
LocalBuffer[Count++] = '\t';
break;
/* Send the current user name. */
case 'U':
break;
/* Send a break across the serial line. */
case 'X':
break;
/* Feed the contents of the
* clipboard into the input
* stream.
*/
case 'I':
if(Count)
ConProcess(LocalBuffer,Count);
Count = LoadClip(LocalBuffer,256);
break;
/* Send a string to the clipboard. */
case 'G':
if(String[i + 1])
SaveClip(&String[i + 1],strlen(&String[i + 1]));
return;
/* Produce the escape character. */
case 'E':
LocalBuffer[Count++] = ESC;
break;
/* Call a menu item. */
case 'C':
break;
/* Stuff the character into the buffer. */
default:
LocalBuffer[Count++] = String[i];
break;
}
GotControl = FALSE;
}
}
/* If the buffer is full, release it. */
if(Count == 256)
{
ConProcess(LocalBuffer,Count);
Count = 0;
}
}
if(Count)
ConProcess(LocalBuffer,Count);
}
/* ConBypass(STRPTR String,LONG Size):
*
* Bypass the `normal' ConOutput() data processing.
*/
VOID __regargs
ConBypass(STRPTR String,LONG Size)
{
if(Size < 0)
Size = strlen(String);
if(Size > 0)
{
ObtainTerminal();
if(Marking)
DropMarker();
ClearCursor();
(*ConProcessData)(String,Size);
DrawCursor();
ReleaseTerminal();
}
}
/* ConProcess(STRPTR String,LONG Size):
*
* Process the contents of a string to be sent to the
* console window.
*/
VOID
ConProcess(register STRPTR String,register LONG Size)
{
/* If the capture filter happens to be disabled, write the
* raw data.
*/
if(!Config -> CaptureConfig -> CaptureFilterMode)
CaptureToFile(String,Size);
/* Feed the flow filter. */
if(UseFlow)
{
if(Config -> SerialConfig -> StripBit8)
FlowFilter(String,Size,0x7F);
else
FlowFilter(String,Size,0xFF);
}
/* Remember the data. */
if(RememberOutput)
RememberOutputText(String,Size);
/* Check the traps if necessary. */
if(WatchTraps)
TrapFilter(String,Size);
/* In quiet mode no characters are echoed to the
* console window, they are just passed through
* the data flow filter. Usually, this mode is
* enabled by the dial panel.
*/
if(!Quiet)
PostData(String,Size);
}
/* ConWrites(STRPTR String,...):
*
* Output a string to the console.
*/
VOID __stdargs
ConWrites(STRPTR String,...)
{
va_list VarArgs;
if(Marking)
DropMarker();
va_start(VarArgs,String);
VSPrintf(SharedBuffer,String,VarArgs);
va_end(VarArgs);
ConProcess(SharedBuffer,strlen(SharedBuffer));
}
/* FlowInit():
*
* Set up the data flow parser. The parser scans the serial
* output data for more or less interesting modem output
* (carrier lost, connect, etc.).
*/
VOID __regargs
FlowInit(BYTE FullReset)
{
WORD i;
/* Set up `NO CARRIER' message. */
if(Config -> ModemConfig -> NoCarrier[0])
SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
else
AttentionBuffers[SCAN_NOCARRIER][0] = 0;
/* Set up ZRQINIT message. */
strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
/* Set up `CONNECT' message. */
strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
/* Set up `VOICE' message. */
if(Config -> ModemConfig -> Voice[0])
SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
else
AttentionBuffers[SCAN_VOICE][0] = 0;
/* Set up `RING' message. */
if(Config -> ModemConfig -> Ring[0])
SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
else
AttentionBuffers[SCAN_RING][0] = 0;
/* Set up `BUSY' message. */
if(Config -> ModemConfig -> Busy[0])
SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
else
AttentionBuffers[SCAN_BUSY][0] = 0;
/* Set up `NO DIALTONE' message. */
if(Config -> ModemConfig -> NoDialTone[0])
SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
else
AttentionBuffers[SCAN_NODIALTONE][0] = 0;
/* Set up `OK' message. */
if(Config -> ModemConfig -> Ok[0])
SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
else
AttentionBuffers[SCAN_OK][0] = 0;
/* Set up `ERROR' message. */
if(Config -> ModemConfig -> Error[0])
SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
else
AttentionBuffers[SCAN_ERROR][0] = 0;
/* Reset match counter. */
FlowCount = 0;
/* Reset indices. */
memset(AttentionCount,0,sizeof(AttentionCount));
/* Determine lengths. */
for(i = 0 ; i < SCAN_COUNT ; i++)
AttentionLength[i] = strlen(AttentionBuffers[i]);
if(FullReset)
{
/* No, we are not yet looking for a baud rate. */
BaudPending = FALSE;
/* Reset the flags. */
memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
}
/* Is it safe to disable the flow filter? */
if(!FullCheck && Online && Config -> SerialConfig -> CheckCarrier && !Config -> MiscConfig -> AutoUpload)
UseFlow = FALSE;
else
UseFlow = TRUE;
/* Full data check is a lot slower than looking for
* just a single sequence (such as the `CONNECT'
* below). This mode is reserved for the dial panel.
*/
if(FullCheck)
{
ScanStart = 0;
ScanEnd = SCAN_COUNT - 1;
}
else
{
if(Online)
{
ScanStart = SCAN_NOCARRIER;
if(UsesZModem)
ScanEnd = SCAN_ZMODEM;
else
ScanEnd = SCAN_NOCARRIER;
}
else
{
if(UsesZModem)
ScanStart = SCAN_ZMODEM;
else
ScanStart = SCAN_CONNECT;
ScanEnd = SCAN_RING;
}
}
}
/* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
*
* Text output, if necessary switching from gfx font
* to current default font.
*/
VOID __regargs
GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
{
BYTE TextMode;
LONG SameMode;
/* Determine current text rendering mode. */
if(GfxTable[Buffer[0]] == MODE_GFX)
TextMode = MODE_GFX;
else
{
TextMode = MODE_STANDARD;
SetFont(RPort,TextFont);
}
/* Reset number of characters in common mode. */
SameMode = 0;
/* Scan until all input is processed. */
FOREVER
{
/* Scan for characters in the current mode. */
while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
SameMode++;
/* Output the text found. */
Text(RPort,Buffer,SameMode);
/* Decrement number of remaining bytes. */
Length -= SameMode;
/* Anything left? */
if(Length)
{
/* Skip to next character. */
Buffer += SameMode;
SameMode = 0;
/* Change text output mode. */
if(TextMode == MODE_GFX)
{
SetFont(RPort,TextFont);
TextMode = MODE_STANDARD;
}
else
{
SetFont(RPort,GFX);
TextMode = MODE_GFX;
}
}
else
break;
}
/* Reset font type. */
if(TextMode == MODE_STANDARD)
SetFont(RPort,GFX);
}
/* ConvertKey():
*
* The actual key conversion routine.
*/
STATIC LONG __inline
ConvertKey(ULONG Qualifier,UWORD Code,ULONG Prev,STRPTR Buffer,LONG Len)
{
LONG Actual;
/* Fill in the defaults. */
FakeInputEvent -> ie_Code = Code;
FakeInputEvent -> ie_Qualifier = Qualifier;
FakeInputEvent -> ie_position . ie_addr = (APTR)Prev;
/* Clear the buffer (sortof). */
Buffer[0] = 0;
/* Convert the codes. */
if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
return(Actual);
else
return(0);
}
/* ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev):
*
* Much more simplified raw key conversion routine.
*/
UBYTE __regargs
ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev)
{
if(Buffer)
Buffer[0] = 0;
if(Len)
*Len = 0;
/* Key was pressed, not released. */
if(!(Code & IECODE_UP_PREFIX))
{
/* These are the sequences mapped to special
* control keys (cursor keys, function keys,
* the help key).
*/
STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
{
(STRPTR)"A", CUP,
(STRPTR)"B", CDN,
(STRPTR)"C", CFW,
(STRPTR)"D", CBK,
(STRPTR)"?~", HLP,
(STRPTR)"0~", FN1,
(STRPTR)"1~", FN2,
(STRPTR)"2~", FN3,
(STRPTR)"3~", FN4,
(STRPTR)"4~", FN5,
(STRPTR)"5~", FN6,
(STRPTR)"6~", FN7,
(STRPTR)"7~", FN8,
(STRPTR)"8~", FN9,
(STRPTR)"9~", F10
};
STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
UBYTE ConvertBuffer[257];
LONG Actual;
/* If it's a function or cursor key, clear the qualifier. */
if(Code >= CURSOR_UP_CODE && Code <= F10_CODE)
Qualifier = NULL;
else
{
/* Does it have a numeric keypad qualifier set? */
if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
{
/* Look at the vanilla result. */
if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Code,Prev,ConvertBuffer,1))
{
STRPTR String;
/* Take a look at the results. */
switch(ConvertBuffer[0])
{
case '(':
case '[':
String = "\033OP";
break;
case ')':
case ']':
String = "\033OQ";
break;
case '/':
String = "\033OR";
break;
case '*':
String = "\033OS";
break;
default:
String = NULL;
break;
}
if(!String)
{
switch(Code)
{
case 0x5A:
String = "\033OP";
break;
case 0x5B:
String = "\033OQ";
break;
case 0x5C:
String = "\033OR";
break;
case 0x5D:
String = "\033OS";
break;
}
}
/* Return the PFx key code. */
if(String)
{
if(Buffer)
memcpy(Buffer,String,3);
if(Len)
*Len = 3;
return('\033');
}
}
}
/* Does it have a shift qualifier set? */
if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
{
/* Do the conversion... */
if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Code,Prev,ConvertBuffer,1))
{
/* Did it produce a tab key? If so, transfer
* Esc tab instead.
*/
if(ConvertBuffer[0] == '\t')
{
if(Len)
*Len = 2;
if(Buffer)
memcpy(Buffer,"\033\t",2);
return('\033');
}
}
}
/* Does it have the control qualifier set? */
if(Qualifier & IEQUALIFIER_CONTROL)
{
/* Do the conversion... */
if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Code,Prev,ConvertBuffer,1))
{
/* Did it produce a space or an `at' sign? */
if(ConvertBuffer[0] == ' ' || ConvertBuffer[0] == '@')
{
/* If so, produce a nul instead. */
if(Len)
*Len = 1;
if(Buffer)
Buffer[0] = 0;
return(0);
}
}
}
}
/* Do the final conversion... */
if(Actual = ConvertKey(Qualifier,Code,Prev,ConvertBuffer,256))
{
/* Are we to swap the backspace and
* delete keys?
*/
if(Config -> EmulationConfig -> SwapBSDelete)
{
register WORD i;
for(i = 0 ; i < Actual ; i++)
{
if(ConvertBuffer[i] == BKS)
ConvertBuffer[i] = DEL;
else
{
if(ConvertBuffer[i] == DEL)
ConvertBuffer[i] = BKS;
}
}
}
/* Translated sequence starts
* with a CSI, let's have a look
* at the associated control
* key.
*/
if(ConvertBuffer[0] == CSI)
{
register WORD i;
for(i = 0 ; i < sizeof(SeqLens) ; i++)
{
/* Does it match? */
if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
{
/* Store the length. */
if(Len)
*Len = 1;
/* Store the result. */
if(Buffer)
{
Buffer[0] = ConversionTable[i] . Result;
Buffer[1] = 0;
}
return(ConversionTable[i] . Result);
}
}
}
/* Store the number of characters converted. */
if(Len)
*Len = Actual;
/* Store the converted characters. */
if(Buffer)
memcpy(Buffer,ConvertBuffer,Actual);
return(ConvertBuffer[0]);
}
}
return(0);
}
/* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
*
* Convert a raw key information according to the
* current keymap settings.
*/
UBYTE __regargs
KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
{
/* Is this really a keyboard event? */
if(Massage -> Class == IDCMP_RAWKEY)
return(ConvertTheKey(Buffer,Len,Massage -> Code,Massage -> Qualifier,*(ULONG *)Massage -> IAddress));
else
{
if(Buffer)
Buffer[0] = 0;
if(Len)
*Len = 0;
return(0);
}
}
/* DoBackspace():
*
* Special function: perform backspace.
*/
BYTE
DoBackspace()
{
Capture("\b",1);
if(CursorX)
{
WORD DeltaX,MinX;
CursorX--;
// What backspace mode are we in?
switch(Config -> EmulationConfig -> DestructiveBackspace)
{
// Do nothing
case 0:
ClipBlitCursor(FALSE,TRUE);
break;
// Shift the line to the left
case 2:
BackupRender();
RasterEraseCharacters(1);
if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
DeltaX = TextFontWidth;
MinX = MUL_X(CursorX);
}
else
{
DeltaX = TextFontWidth / 2;
MinX = MUL_X(CursorX) / 2;
}
}
else
{
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
{
DeltaX = TextFontWidth / 2;
MinX = MUL_X(CursorX) / 2;
}
else
{
DeltaX = TextFontWidth;
MinX = MUL_X(CursorX);
}
}
ScrollLineEraseCharacters(1);
ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
BackupRender();
ClipBlitCursor(FALSE,TRUE);
break;
// Clear the character below the cursor
default:
ClipBlitCursor(FALSE,TRUE);
ObtainSemaphore(RasterSemaphore);
Raster[CursorY * RasterWidth + CursorX] = ' ';
ReleaseSemaphore(RasterSemaphore);
BackupRender();
if(FontScalingRequired)
PrintScaled(" ",1,CurrentFontScale);
else
Text(RPort," ",1);
BackupRender();
break;
}
}
return(FALSE);
}
/* DoBeep():
*
* The real interface to the beep routine.
*/
BYTE
DoBeep()
{
BellSignal();
/* Capture the bell. */
if(Config -> CaptureConfig -> CaptureFilterMode == FILTER_NONE)
Capture("\a",1);
return(FALSE);
}
/* DoxON():
*
* Perform XON (stop data flow).
*/
BYTE
DoxON()
{
if(Config -> SerialConfig -> xONxOFF)
Status = STATUS_HOLDING;
return(FALSE);
}
/* DoLF():
*
* Special function: perform line feed.
*/
BYTE
DoLF()
{
if(Config -> TerminalConfig -> ReceiveLF == LF_ASLFCR)
{
CursorX = 0;
DownLine();
ClipBlitCursor(FALSE,TRUE);
Capture("\n",1);
}
else
{
if(Config -> TerminalConfig -> ReceiveLF == LF_ASLF)
{
DownLine();
ClipBlitCursor(FALSE,TRUE);
}
}
return(FALSE);
}
/* DoShiftIn():
*
* Special function: Shift into graphics mode
*/
BYTE
DoShiftIn()
{
if(CharMode[1] == TABLE_GFX && GFX)
CurrentFont = GFX;
if(CharMode[1] == TABLE_ASCII)
CurrentFont = TextFont;
SetFont(RPort,CurrentFont);
ConOutputUpdate();
Charset = 1;
return(FALSE);
}
/* DoShiftOut():
*
* Special function: Shift out of graphics mode
*/
BYTE
DoShiftOut()
{
if(CharMode[0] == TABLE_GFX && GFX)
CurrentFont = GFX;
if(CharMode[0] == TABLE_ASCII)
CurrentFont = TextFont;
SetFont(RPort,CurrentFont);
ConOutputUpdate();
Charset = 0;
return(FALSE);
}
/* DoCR_LF():
*
* Special function: perform carriage return and line feed.
*/
BYTE
DoCR_LF()
{
CursorX = 0;
DownLine();
ClipBlitCursor(FALSE,TRUE);
Capture("\n",1);
return(FALSE);
}
/* DoFF():
*
* Special function: perform form feed.
*/
BYTE
DoFF()
{
if(Config -> EmulationConfig -> NewLineMode)
{
CursorX = 0;
DoCR_LF();
}
else
{
EraseScreen("2");
CursorX = CursorY = 0;
ClipBlitCursor(FALSE,TRUE);
ConFontScaleUpdate();
Capture("\n",1);
}
return(FALSE);
}
/* DoLF_FF_VT():
*
* Special function: handle line feed, form feed and vertical
* tab.
*/
BYTE
DoLF_FF_VT()
{
if(Config -> EmulationConfig -> NewLineMode)
DoCR_LF();
else
DoLF();
return(FALSE);
}
/* DoCR():
*
* Special function: handle carriage return.
*/
BYTE
DoCR()
{
if(Config -> EmulationConfig -> NewLineMode || Config -> TerminalConfig -> ReceiveCR == CR_ASCRLF)
DoCR_LF();
else
{
if(Config -> TerminalConfig -> ReceiveCR == CR_ASCR)
{
CursorX = 0;
ClipBlitCursor(FALSE,TRUE);
Capture("\n",1);
}
}
return(FALSE);
}
/* DoTab():
*
* Special function: handle tab, move cursor to next
* tab stop.
*/
BYTE
DoTab()
{
WORD Column;
if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
Column = LastColumn;
else
Column = ((LastColumn + 1) / 2) - 1;
if(Config -> EmulationConfig -> LineWrap)
{
if(CursorX >= LastColumn)
{
CursorX = 0;
DownLine();
}
else
{
while(CursorX < Column)
{
CursorX++;
if(TabStops[CursorX])
break;
}
}
}
else
{
while(CursorX < Column)
{
CursorX++;
if(TabStops[CursorX])
break;
}
}
ClipBlitCursor(FALSE,TRUE);
Capture("\t",1);
return(FALSE);
}
/* DoEnq():
*
* Special function: send answerback message.
*/
BYTE
DoEnq()
{
if(Config -> EmulationConfig -> AnswerBack[0])
SerialCommand(Config -> EmulationConfig -> AnswerBack);
return(FALSE);
}
/* DoEsc():
*
* Start new control sequence.
*/
BYTE
DoEsc()
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^",1);
return(TRUE);
}
/* DoCsi():
*
* Start new control sequence.
*/
BYTE
DoCsi()
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^[",2);
ParseCode('[');
return(TRUE);
}
/* DoNewEsc(UBYTE Char):
*
* Start new control sequence.
*/
BYTE
DoNewEsc(UBYTE Char)
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^",1);
DoCancel();
return(TRUE);
}
/* DoNewCsi(UBYTE Char):
*
* Start new control sequence.
*/
BYTE
DoNewCsi(UBYTE Char)
{
if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
(* ConDump)("^[",2);
DoCancel();
return(ParseCode('['));
}